/*
    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) 2012  Jeremy W. Murphy <jeremy.william.murphy@gmail.com>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef FUNCTION_H
#define FUNCTION_H

/*  TODO: Eventually the concrete classes will be moved out into plugins.
    For now they reside here to streamline finishing the proof of concept.  */


#include "node.h"

#include <array>
#include <iterator>


namespace rmitgprime
{
    template <typename ReturnType = double, unsigned arity = 2u>
    class Function : public Node<ReturnType>
    {
        public:
            // Function(std::array<Node<ReturnType> *, arity> const &children) : children(children) { };
            virtual ReturnType operator*() const = 0;
            typename std::array<Node<ReturnType> *, arity>::const_iterator begin() const { return children.begin(); };
            void add_child(Node<ReturnType> const *child);

        protected:
            std::array<Node<ReturnType> *, arity> children;
    };


    template <typename ReturnType, unsigned arity>
    class Root : public Function<ReturnType, arity>
    {
        public:
            Root() : evaluated(false) {};
            virtual ReturnType operator*() const
            {
                // TODO: Hmmm, this does not work... how to make it work?
                if (evaluated)
                    return result;
                else
                {

                }
            };

        private:
            ReturnType result;
            bool evaluated;
    };
}

#endif // FUNCTION_H
